package com.ctos.ojbackendquestionservice.service.impl;


import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctos.ojbackendcommon.common.ErrorCode;
import com.ctos.ojbackendcommon.constant.CommonConstant;
import com.ctos.ojbackendcommon.constant.RabbitMqConstant;
import com.ctos.ojbackendcommon.exception.BusinessException;
import com.ctos.ojbackendcommon.utils.SqlUtils;
import com.ctos.ojbackendmodel.dto.questionsubmit.QuestionSubmitAddRequest;
import com.ctos.ojbackendmodel.dto.questionsubmit.QuestionSubmitQueryRequest;
import com.ctos.ojbackendmodel.entity.Question;
import com.ctos.ojbackendmodel.entity.QuestionSubmit;
import com.ctos.ojbackendmodel.entity.User;
import com.ctos.ojbackendmodel.enums.QuestionSubmitLanguageEnum;
import com.ctos.ojbackendmodel.enums.QuestionSubmitStatusEnum;
import com.ctos.ojbackendmodel.vo.QuestionSubmitVO;
import com.ctos.ojbackendquestionservice.mapper.QuestionSubmitMapper;
import com.ctos.ojbackendquestionservice.mq.QuestionMessageProducer;
import com.ctos.ojbackendquestionservice.service.QuestionService;
import com.ctos.ojbackendquestionservice.service.QuestionSubmitService;
import com.ctos.ojbackendserviceclient.service.JudgeFeignClient;
import com.ctos.ojbackendserviceclient.service.UserFeignClient;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

import static com.ctos.ojbackendcommon.constant.RabbitMqConstant.JUDGE_QUESTION_EXCHANGE_NAME;
import static com.ctos.ojbackendcommon.constant.RabbitMqConstant.JUDGE_QUESTION_ROUTING_KEY;

/**
* @author ctOS
* @description 针对表【question_submit(题目提交)】的数据库操作Service实现
* @createDate 2025-02-19 10:06:59
*/
@Service
public class QuestionSubmitServiceImpl extends ServiceImpl<QuestionSubmitMapper, QuestionSubmit>
implements QuestionSubmitService {
    @Resource
    private QuestionService questionService ;

    @Resource
    private UserFeignClient userFeignClient;

    @Resource
    private QuestionMessageProducer messageProducer;

    /**
     * 提交题目信息
     *
     * @param questionSubmitAddRequest
     * @param loginUser
     * @return
     */
    @Override
    public long doQuestionSubmit(QuestionSubmitAddRequest questionSubmitAddRequest, User loginUser) {

        // 判断实体是否存在，根据类别获取实体
        Question question = questionService.getById(questionSubmitAddRequest.getQuestionId());
        String language = questionSubmitAddRequest.getLanguage();
        QuestionSubmitLanguageEnum enumByText = QuestionSubmitLanguageEnum.getEnumByText(language);
        if (question == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        if(enumByText == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "不支持的编程语言");
        }

        // 是否已题目
        long userId = loginUser.getId();
        // 每个用户串行题目
        QuestionSubmit questionSubmit = new QuestionSubmit();
        questionSubmit.setStatus(QuestionSubmitStatusEnum.WAITING.getValue());
        questionSubmit.setQuestionId(questionSubmitAddRequest.getQuestionId());
        questionSubmit.setCode(questionSubmitAddRequest.getCode());
        questionSubmit.setUserId(userId);
        questionSubmit.setLanguage(questionSubmitAddRequest.getLanguage());
        questionSubmit.setJudgeInfo("{}");
        boolean result = this.save(questionSubmit);
        if (!result) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "提交失败");
        }
        // 执行判题服务 修改题目提交信息表
        Long id = questionSubmit.getId();
        // CompletableFuture.runAsync(() ->{
        //    judgeFeignClient.doJudge(id);
        // }).exceptionally(ex -> {
        //     log.error("Error in judge task for question submit ID: {}",  ex);
        //     return null;
        // });
        messageProducer.sendMessage(JUDGE_QUESTION_EXCHANGE_NAME, JUDGE_QUESTION_ROUTING_KEY, String.valueOf(id));
        return id;

    }

    /**
     * 获取查询包装类 用户根据哪些字段查询
     *
     * @param questionQueryRequest
     * @return
     */
    @Override
    public QueryWrapper<QuestionSubmit> getQueryWrapper(QuestionSubmitQueryRequest questionQueryRequest) {
        QueryWrapper<QuestionSubmit> queryWrapper = new QueryWrapper<>();
        if (questionQueryRequest == null) {
            return queryWrapper;
        }

        String language = questionQueryRequest.getLanguage();
        Long userId = questionQueryRequest.getUserId();
        Integer status = questionQueryRequest.getStatus();
        Long questionId = questionQueryRequest.getQuestionId();


        queryWrapper.eq(ObjectUtils.isNotEmpty(questionId), "questionId ", questionId);
        queryWrapper.eq(StringUtils.isNotEmpty(language), "language ", language);
        queryWrapper.eq(QuestionSubmitStatusEnum.getEnumByValue(status) != null, "status ", status);

        queryWrapper.eq(ObjectUtils.isNotEmpty(userId), "userId", userId);


        String sortField = questionQueryRequest.getSortField();
        String sortOrder = questionQueryRequest.getSortOrder();


        queryWrapper.orderBy(SqlUtils.validSortField(sortField), sortOrder.equals(CommonConstant.SORT_ORDER_ASC),
                sortField);
        return queryWrapper;
    }

    /**
     * 脱敏
     * @param questionSubmit
     *  @param loginUser
     * @return
     */
    @Override
    public QuestionSubmitVO getQuestionSubmitVO(QuestionSubmit questionSubmit, User loginUser) {
        QuestionSubmitVO questionVO = QuestionSubmitVO.objToVo(questionSubmit);
        Long userId = questionSubmit.getUserId();
        Long loginId = loginUser.getId();
        //只有管理员或者提交题目本人可以查看代码
        if (!loginId.equals(userId)&&!userFeignClient.isAdmin(loginUser) ){
            questionVO.setCode("");
        }

        return questionVO;
    }

    @Override
    public Page<QuestionSubmitVO> getQuestionSubmitVOPage(Page<QuestionSubmit> questionSubmitPage, User loginUser) {
        List<QuestionSubmit> questionList = questionSubmitPage.getRecords();
        Page<QuestionSubmitVO> questionVOPage = new Page<>(questionSubmitPage.getCurrent()
                , questionSubmitPage.getSize(), questionSubmitPage.getTotal());
        if (CollUtil.isEmpty(questionList)) {
            return questionVOPage;
        }
        // 1. 关联查询用户信息
        Set<Long> userIdSet = questionList.stream().map(QuestionSubmit::getUserId).collect(Collectors.toSet());
        Map<Long, List<User>> userIdUserListMap = userFeignClient.listByIds(userIdSet).stream()
                .collect(Collectors.groupingBy(User::getId));

        // 填充信息
        List<QuestionSubmitVO> questionVOList = questionList.stream().map(question -> {
            QuestionSubmitVO questionVO = QuestionSubmitVO.objToVo(question);
            Long userId = question.getUserId();
            User user = null;
            if (userIdUserListMap.containsKey(userId)) {
                user = userIdUserListMap.get(userId).get(0);
            }
            questionVO.setUserVO(userFeignClient.getUserVO(user));

            return questionVO;
        }).collect(Collectors.toList());
        questionVOPage.setRecords(questionVOList);
        return questionVOPage;
    }

}

